package cn.tiger.threadPool;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 本代码介绍创建线程池的多种方式，以及适用场景  <br>
 * 生产环境推荐使用 ThreadPoolExecutor 直接创建，避免使用 Executors 的预设方法（可能引发 OOM） <br>
 * <b>根据任务类型选择队列：</b> <br>
 * CPU 密集型：ArrayBlockingQueue（固定大小） <br>
 * IO 密集型：SynchronousQueue（直接传递） <br>
 * 混合型：LinkedBlockingQueue（无界队列） <br><br>
 * <b>合理设置拒绝策略：</b> <br>
 * AbortPolicy（默认，抛出异常） <br>
 * CallerRunsPolicy（调用者线程执行） <br>
 * DiscardPolicy（静默丢弃） <br>
 * DiscardOldestPolicy（丢弃最旧任务） <br>
 * <br>
 * <b>参数设置经验值：</b> <br>
 * CPU 密集型：核心线程数 = CPU核心数 + 1 <br>
 * IO 密集型：核心线程数 = CPU核心数 * 2 <br>
 * 队列容量：根据系统可承受峰值设置（通常 100-10000） <br>
 * 最大线程数：根据系统资源设置（通常为核心线程数的 2-5 倍） <br>
 */
public class ThreadPoolDemo {

    /**
     * Spring 创建线程池
     * 该方式创建的线程池，可以自动注入到 Spring 容器中
     * 使用：
     * @Autowired
     * private ExecutorService taskExecutor;
     *
     * taskExecutor.execute(() -> {}); // 提交任务
     * 或者：
     * taskExecutor.execute(new Runnable() {
     *      @Override
     *      public void run() {}
     * });
     * 或在方法上使用@Async注解
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("SpringPool-");
        executor.initialize();
        return executor;
    }

    @Autowired
     private ExecutorService taskExecutor;

    public static void main(String[] args) throws InterruptedException {
        fixedThreadPoolExample(); // 固定线程池
        cachedThreadPoolExample(); // 缓存线程池
        singleThreadExecutorExample(); // 单线程线程池
        scheduledThreadPoolExample(); // 定时线程池
        workStealingPoolExample(); // 工作窃取线程池
        ThreadPoolExecutorExample(); // 自定义线程池

        // spring线程池执行案例
        //SpringThreadPoolExecutorExample(); // spring线程池  这里编译报错是正常的 静态方法无法调用非静态方法
        //SpringThreadPoolAsyncExample(); // spring异步执行 这里编译报错是正常的  静态方法无法调用非静态方法

    }

    private void SpringThreadPoolExecutorExample() {
        // 提交任务(有返回值)
        Future<?> springThreadPoolExecutorSubmit = taskExecutor.submit(() -> System.out.println("SpringThreadPoolExecutor submit"));
        // 提交任务(无返回值)
        taskExecutor.execute(() -> System.out.println("SpringThreadPoolExecutor execute"));
    }

    @Async
    public void SpringThreadPoolAsyncExample() {
            System.out.println("SpringThreadPoolAsyncExample");
    }


    /**
     * FixedThreadPool 示例
     * - 固定3个线程，使用无界队列
     */
    public static void fixedThreadPoolExample() throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        AtomicInteger counter = new AtomicInteger(0);

        // 提交10个任务
        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                System.out.println("[Fixed] Task " + counter.incrementAndGet()
                        + " executed by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(500); // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        Thread.sleep(3000);
        executor.shutdown();
    }

    /**
     * CachedThreadPool 示例
     * - 弹性线程数，适合短期任务
     */
    public static void cachedThreadPoolExample() throws InterruptedException {
        ExecutorService executor = Executors.newCachedThreadPool();
        AtomicInteger counter = new AtomicInteger(0);

        // 提交10个快速任务
        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                System.out.println("[Cached] Task " + counter.incrementAndGet()
                        + " executed by " + Thread.currentThread().getName());
            });
        }

        Thread.sleep(1000);
        executor.shutdown();
    }

    /**
     * SingleThreadExecutor 示例
     * - 单线程顺序执行任务
     */
    public static void singleThreadExecutorExample() throws InterruptedException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        AtomicInteger counter = new AtomicInteger(0);

        // 提交5个任务
        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                System.out.println("[Single] Task " + counter.incrementAndGet()
                        + " executed by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        Thread.sleep(1500);
        executor.shutdown();
    }

    /**
     * ScheduledThreadPool 示例
     * - 定时/周期性任务调度
     */
    public static void scheduledThreadPoolExample() throws InterruptedException {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

        // 延迟3秒后执行
        executor.schedule(() -> {
            System.out.println("[Scheduled] Delayed task executed by "
                    + Thread.currentThread().getName());
        }, 3, TimeUnit.SECONDS);

        // 周期性任务：首次延迟1秒，之后每2秒执行一次
        executor.scheduleAtFixedRate(() -> {
            System.out.println("[Scheduled] Periodic task executed by "
                    + Thread.currentThread().getName());
        }, 1, 2, TimeUnit.SECONDS);

        Thread.sleep(7000);
        executor.shutdown();
    }

    /**
     * WorkStealingPool 示例 (Java 8+)
     * - 工作窃取线程池，并行处理任务
     */
    public static void workStealingPoolExample() throws InterruptedException {
        ExecutorService executor = Executors.newWorkStealingPool(4);
        AtomicInteger counter = new AtomicInteger(0);

        // 提交20个任务
        for (int i = 0; i < 20; i++) {
            executor.submit(() -> {
                System.out.println("[WorkStealing] Task " + counter.incrementAndGet()
                        + " executed by " + Thread.currentThread().getName());
                try {
                    Thread.sleep(100); // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }

        // 等待所有任务完成
        executor.shutdown();
        if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
            executor.shutdownNow();
        }
    }

    /**
     * 自定义线程池示例
     * - 根据CPU核心数动态设置线程池大小
     * - 根据任务类型选择队列
     * - 根据系统资源设置最大线程数
     * - 根据系统资源设置拒绝策略
     * - 根据系统资源设置线程工厂
     * - 完全自定义线程池
     * - 优雅关闭线程池
     * - 线程池监控
     */
    private static void ThreadPoolExecutorExample() {
        // 根据CPU核心数动态设置线程池大小
        final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors();
        final int MAX_POOL_SIZE = CORE_POOL_SIZE * 2;
        final int QUEUE_CAPACITY = 100;
        final long KEEP_ALIVE_TIME = 60L;
        // 6. 完全自定义参数
        ThreadPoolExecutor customPool = new ThreadPoolExecutor(
                CORE_POOL_SIZE,                      // 核心线程数
                MAX_POOL_SIZE,                     // 最大线程数
                KEEP_ALIVE_TIME,                    // 空闲线程存活时间
                TimeUnit.SECONDS,       // 时间单位
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),  // 任务队列
                Executors.defaultThreadFactory(), // 线程工厂
                new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
        );
        // 提交任务
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            customPool.execute(() -> {
                try {
                    System.out.println(Thread.currentThread().getName()
                            + " 正在执行任务 " + taskId);
                    // 模拟业务处理
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 优雅关闭线程池
        customPool.shutdown();
        try {
            if (!customPool.awaitTermination(60, TimeUnit.SECONDS)) {
                customPool.shutdownNow();
            }
        } catch (InterruptedException e) {
            customPool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

}
